﻿using System;
using Tao.OpenGl;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Aeon.Framework
{   

/// <summary>
/// Textures OpenGL and memory data implementation class.
/// Can be created empty or loaded, and is immutable except when disposed.
/// 
///     [TODO] Bumpmaps.
/// 
/// </summary>
public sealed class TextureCore
    {
    // --- Attributes:

    private TextureType image;                          // File format data loader.
    private String path;                                // Texture file path.
    
    private Boolean rendered;                           // Data rendered on context flag.
    private Boolean empty;                              // Texture contains data flag.
    private Int32 texture;                              // OpenGL texture pointer.
    private Byte[] data;                                // Image bytes array.

    // --- Properties:

    public static TextureCore NoData = new TextureCore("Empty");

    public String Path { get { return(path); } }
    public Boolean Empty { get { return(empty); } }
    
    public UInt16 Width { get { if(!empty) return(image.Width); else return(0); } }
    public UInt16 Height { get { if (!empty) return(image.Height); else return(0); } }

    // --- Constructor:

    internal TextureCore(String filepath)
        {
        path = filepath;

        if (path != "Empty") load();
        else unload();
        }

    // --- Internal Methods:

    private void load()
        {
        image = new TextureType();
        data = image.Load(path);

        rendered = false;
        empty = false;
        }

    private void unload()
        {
        image = null;
        data = null;

        rendered = true;
        texture = 0;

        path = "Empty";
        empty = true;
        }

    // --- Public Methods:

    /// <summary>
    /// Binds data to active context.
    /// 
    /// </summary> 0
    public void Bind()
        {
        if (!rendered)
            {
            Gl.glGenTextures(1,out texture);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D,texture);
            
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D,Gl.GL_TEXTURE_MAG_FILTER,Gl.GL_LINEAR); // [TODO] Mipmap it!
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D,Gl.GL_TEXTURE_MIN_FILTER,Gl.GL_NEAREST);

            Gl.glTexImage2D(Gl.GL_TEXTURE_2D,0,image.Input,image.Width,image.Height,0,image.Output,image.Format,data);
            //Glu.gluBuild2DMipmaps(Gl.GL_TEXTURE_2D,image.Input,image.Width,image.Height,image.Output,image.Format,data);
            
            rendered = true;
            }
        
        Gl.glBindTexture(Gl.GL_TEXTURE_2D,texture);
        }

    /// <summary>
    /// Cleans data from OpenGL.
    /// 
    /// </summary>
    public void Dispose()
        {
        if (texture != 0) 
            {
            Gl.glDeleteTextures(1,ref texture);
            rendered = false;
            texture = 0;
            }

        if (!empty) unload();
        }

    }


}